/*
 * @Author: hx 2542123711@QQ.com
 * @Date: 2024-12-17 15:40:51
 * @LastEditors: hx 2542123711@QQ.com
 * @LastEditTime: 2025-01-11 18:47:05
 * @FilePath: /class_thread/thread-poll/ThreadPoll.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
// #pragma once

// #include <iostream>
// #include <vector>
// #include <pthread.h>
// #include <string>
// #include <queue>
// #include <unistd.h>
// #include"Task.hpp"

// using namespace std;

// struct thread
// {
//     pthread_t _tid;
//     string _name;
// };

// const int defaultcap = 5;

// template <class T>
// class ThreadPoll
// {
// public:
//     void Lock()
//     {
//         pthread_mutex_lock(&_mutex);
//     }

//     void Unlock()
//     {
//         pthread_mutex_unlock(&_mutex);
//     }

//     void ThreadSleep()
//     {
//         pthread_cond_wait(&_cond, &_mutex);
//     }

//     void ThreadWake()
//     {
//         pthread_cond_signal(&_cond);
//     }

//     string threadname(pthread_t tid)
//     {
//         for (int i = 0; i < _threads.size(); i++)
//         {
//             if (_threads[i]._tid == tid)
//             {
//                 return _threads[i]._name;
//             }
//         }

//         return "NONE";
//     }

// public:
//     ThreadPoll()
//     {}
    
//     static void *Exaute(void *args)
//     {
//         ThreadPoll<T> *tp = static_cast<ThreadPoll<T> *>(args);

//         const string name = tp->threadname(pthread_self());
//         while (true)
//         {
//             tp->Lock();

//             while(tp->IsQueueEmpty())
//             {
//                 sleep(1000);
//             }

//             T t = tp->pop();
//             tp->Unlock();

//             t();
//         }
//     }
    
//     void Run()
//     {
//         for (int i = 0; i < _cap; i++)
//         {
//             _threads[i]._name = "thread-" + to_string(i + 1);
//             pthread_create(&_threads[i]._tid, nullptr, Exaute, this);
//         }
//     }

//     void push(const T &in)
//     {
//         Lock();
//         _queue.push(in);
//         ThreadWake();
//         Unlock();
//     }

//     T pop()
//     {
//         // Lock();
//         while (_queue.empty())
//         {
//             ThreadSleep();
//         }

//         T out = _queue.front();
//         _queue.pop();
//         // Unlock();

//         return out;
//     }

//     bool IsQueueEmpty()
//     {
//         return _queue.empty();
//     }

//     // 单例模式+懒汉模式
//     static ThreadPoll<T>* GetInstance()
//     {
//         if (_t == nullptr)
//         {
//             pthread_mutex_lock(&_lock);
//             if (_t == nullptr)
//             {
//                 _t = new ThreadPoll<T>(5);
//                 cout << "log: singleton create done first!" << endl;
//             }
//             pthread_mutex_unlock(&_lock);
//         }

//         return _t;
//     }

//     ~ThreadPoll()
//     {
//         pthread_mutex_destroy(&_mutex);
//         pthread_cond_destroy(&_cond);
//     }

// private:
//     ThreadPoll(int cap = defaultcap)
//         : _cap(cap)
//     {
//         _threads.resize(cap);
//         pthread_mutex_init(&_mutex, nullptr);
//         pthread_cond_init(&_cond, nullptr);
//     }

//     //禁止类外对此赋值和拷贝
//     ThreadPoll(const ThreadPoll<T>& t) = delete;
//     const ThreadPoll<T> operator=(const ThreadPoll<T>& t) = delete;
    
// private:
//     vector<thread> _threads;
//     queue<T> _queue;

//     int _cap;
//     pthread_mutex_t _mutex;
//     pthread_cond_t _cond;

//     // 当进程启动的时候只加载该类的指针对象，当需要实例化的时候再调用
//     static ThreadPoll<T> *_t;
//     static pthread_mutex_t _lock;
// };

// // 类型名称 类域::变量名称
// template <class T>
// ThreadPoll<T> *ThreadPoll<T>::_t = nullptr;

// template <class T>
// pthread_mutex_t ThreadPoll<T>::_lock = PTHREAD_MUTEX_INITIALIZER;





#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <pthread.h>
#include <unistd.h>

struct ThreadInfo
{
    pthread_t tid;
    std::string name;
};

static const int defalutnum = 5;

template <class T>
class ThreadPool
{
public:
    void Lock()
    {
        pthread_mutex_lock(&mutex_);
    }

    void Unlock()
    {
        pthread_mutex_unlock(&mutex_);
    }

    void Wakeup()
    {
        pthread_cond_signal(&cond_);
    }

    void ThreadSleep()
    {
        pthread_cond_wait(&cond_, &mutex_);
    }

    bool IsQueueEmpty()
    {
        return tasks_.empty();
    }

    std::string GetThreadName(pthread_t tid)
    {
        for (const auto &ti : threads_)
        {
            if (ti.tid == tid)
                return ti.name;
        }
        return "None";
    }

public:
    static void *HandlerTask(void *args)
    {
        ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args);
        std::string name = tp->GetThreadName(pthread_self());
        
        while (true)
        {
            tp->Lock();

            while (tp->IsQueueEmpty())
            {
                tp->ThreadSleep();
            }
            T t = tp->Pop();
            tp->Unlock();

            t();
        }
    }

    void Start()
    {
        int num = threads_.size();
        for (int i = 0; i < num; i++)
        {
            threads_[i].name = "thread-" + std::to_string(i + 1);
            pthread_create(&(threads_[i].tid), nullptr, HandlerTask, this);
        }
    }

    T Pop()
    {
        T t = tasks_.front();
        tasks_.pop();
        return t;
    }

    void Push(const T &t)
    {
        Lock();
        tasks_.push(t);
        Wakeup();
        Unlock();
    }

    static ThreadPool<T> *GetInstance()
    {
        if (nullptr == tp_) 
        {
            pthread_mutex_lock(&lock_);
            if (nullptr == tp_)
            {
                std::cout << "log: singleton create done first!" << std::endl;
                tp_ = new ThreadPool<T>();
            }
            pthread_mutex_unlock(&lock_);
        }

        return tp_;
    }

private:
    ThreadPool(int num = defalutnum) : threads_(num)
    {
        pthread_mutex_init(&mutex_, nullptr);
        pthread_cond_init(&cond_, nullptr);
    }
    
    ~ThreadPool()
    {
        pthread_mutex_destroy(&mutex_);
        pthread_cond_destroy(&cond_);
    }
    
    ThreadPool(const ThreadPool<T> &) = delete;
    const ThreadPool<T> &operator=(const ThreadPool<T> &) = delete; // a=b=c
private:
    std::vector<ThreadInfo> threads_;
    std::queue<T> tasks_;

    pthread_mutex_t mutex_;
    pthread_cond_t cond_;

    static ThreadPool<T> *tp_;
    static pthread_mutex_t lock_;
};

template <class T>
ThreadPool<T> *ThreadPool<T>::tp_ = nullptr;

template <class T>
pthread_mutex_t ThreadPool<T>::lock_ = PTHREAD_MUTEX_INITIALIZER;